package store.lunangangster.engine.impl.entity;

import java.util.HashMap;
import java.util.Map;
import store.lunangangster.engine.impl.Context;

public class VariableEntityImpl extends EntityImpl implements VariableEntity {

  // DB variable
  protected String executionId;
  protected String processInstanceId;
  protected String type;
  protected String name;
  protected int integerValue;
  protected float floatValue;
  protected double doubleValue;
  protected String stringValue;
  protected String byteArrayId;

  // cache
  protected byte[] bytes;

  @Override
  public String getExecutionId() {
    return executionId;
  }

  @Override
  public String getProcessInstanceId() {
    return processInstanceId;
  }

  @Override
  public String getType() {
    return type;
  }

  @Override
  public String getName() {
    return name;
  }

  @Override
  public Object getValue() {
    if (type == null) {
      return null;
    }
    switch (type) {
      case VariableType.BOOLEAN_TYPE: return !(integerValue == 0);
      case VariableType.INTEGER_TYPE: return integerValue;
      case VariableType.FLOAT_TYPE: return floatValue;
      case VariableType.DOUBLE_TYPE: return doubleValue;
      case VariableType.STRING_TYPE: return stringValue;
      case VariableType.BYTES_TYPE: return bytes;
    }
    return null;
  }

  @Override
  public int getIntegerValue() {
    return integerValue;
  }

  @Override
  public float getFloatValue() {
    return floatValue;
  }

  @Override
  public double getDoubleValue() {
    return doubleValue;
  }

  @Override
  public String getStringValue() {
    return stringValue;
  }

  // lazy load
  @Override
  public byte[] getBytesValue() {
    if (bytes == null && byteArrayId != null) {
      bytes = Context.getProcessEngineConfiguration().getByteArrayManager().selectById(byteArrayId).getBytes();
    }
    return bytes;
  }

  @Override
  public String getByteArrayId() {
    return byteArrayId;
  }

  @Override
  public void setExecutionId(String executionId) {
    this.executionId = executionId;
  }

  @Override
  public void setProcessInstanceId(String processInstanceId) {
    this.processInstanceId = processInstanceId;
  }

  @Override
  public void setType(String type) {
    this.type = type;
  }

  @Override
  public void setName(String name) {
    this.name = name;
  }

  @Override
  public void setValue(Object value) {
    String type = VariableType.resolveType(value);
    if (type == null) {
      return;
    }
    switch (type) {
      case VariableType.BOOLEAN_TYPE: setIntegerValue(((boolean) value) ? 1 : 0); break;
      case VariableType.INTEGER_TYPE: setIntegerValue((int) value); break;
      case VariableType.FLOAT_TYPE: setFloatValue((float) value); break;
      case VariableType.DOUBLE_TYPE: setDoubleValue((double) value); break;
      case VariableType.STRING_TYPE: setStringValue((String) value); break;
      case VariableType.BYTES_TYPE: setBytes((byte[]) value); break;
    }
    setType(type);
  }

  @Override
  public void setIntegerValue(int value) {
    this.integerValue = value;
  }

  @Override
  public void setFloatValue(float value) {
    this.floatValue = value;
  }

  @Override
  public void setDoubleValue(double value) {
    this.doubleValue = value;
  }

  @Override
  public void setStringValue(String value) {
    this.stringValue = value;
  }

  @Override
  public void setBytes(byte[] bytes) {
    this.bytes = bytes;
  }

  @Override
  public void setByteArrayId(String byteArrayId) {
    this.byteArrayId = byteArrayId;
  }

  @Override
  public Object getPersistState() {
    Map<String, Object> persistState = new HashMap<>();
    persistState.put("executionId", executionId);
    persistState.put("processInstanceId", processInstanceId);
    persistState.put("type", type);
    persistState.put("name", name);
    persistState.put("integerValue", integerValue);
    persistState.put("floatValue", floatValue);
    persistState.put("doubleValue", doubleValue);
    persistState.put("stringValue", stringValue);
    persistState.put("byteArrayId", byteArrayId);

    return persistState;
  }
}
